/**
 * Application performance and usability is enhanced by using various caching strategies.  A hard cache is used
 * when storing postings and notes across browser sessions.  A soft cache is used for a single browser session.
 * The hard cache is supported via the dojo storage widget (dojo.storage).  This widget uses the flash plugin,
 * so if a browser does not allow for flash, then a hard cache will not be provided.
 * @author birdeau@yahoo.com
 */
jsx3.lang.Class.defineClass("gicx.Cache", null, [], function(Cache,Cache_prototype) {


  Cache.serialize_throttle;
  Cache.TIMEOUT = 5000;


  /**
   * main method
   */
  Cache_prototype.init = function() {
    this.jsxsuper();
  };


  /**
   * If true, dojo storage is enabled and the hard cache should be activated
   */
  Cache.isEnabled = function() {
    return window.dojo && window.dojo.storage;;
  };


  /**
   * Gets the named document. First tries the in-memory cache. Next tries to restore
   * the document from the dojo storage widget. Finally just instances a new CDF document
   * @param TYPE {jsx3.xml.CDF.Document}
   */
  Cache.getDocument = function(TYPE) {
    var objXML = gicx.APP.getCache().getDocument(TYPE) || Cache.deserialize(TYPE);
    if(jsx3.util.strEmpty(objXML) || !(objXML instanceof jsx3.xml.Document) || objXML.hasError()) {
      var objXML = jsx3.xml.CDF.Document.newDocument();
      gicx.APP.getCache().setDocument(TYPE,objXML);
    }
    return objXML;
  };


  /**
   * Gets a CDF record from a given cache document
   * @param TYPE {String} one of: searchHistory (hard cache), _searchHistory (soft cache)
   * @param strJsxId {String} CDF jsxid
   */
  Cache.getRecord = function(TYPE,strJsxId) {
    var objXML = Cache.getDocument(TYPE);
    return objXML.selectSingleNode("//record[@jsxid='" + strJsxId + "']");
  };


  /**
   * Persists the given CDF record to one of the cacheable CDF documents used by the app (defined by TYPE)
   * @param TYPE {String} one of: searchHistory (hard cache), _searchHistory (soft cache)
   * @param objRN {jsx3.xml.Entity} CDF jsxid
   * @param objPRN {jsx3.xml.Entity} if provided, the new record will be appended to this node;
   * NOTE: objPRN must already be a member of the named document, TYPE
   */
  Cache.setRecord = function(TYPE,objRN,objPRN) {
    //check the cache for the posting
    var objExist = Cache.getRecord(TYPE,objRN.getAttribute("jsxid"));
    if(objExist && objPRN && objExist.getRootNode().equals(objRN.getRootNode())) {
      //this is a move, because objRN is already part of the given DOM;
      //this will support a folder API where favorites can be dragged/dropped in different favorites folders
      objRN.removeAttribute("jsxselected");
      objPRN.appendChild(objRN);
    } else {
      //clone for now; always assume that the original is untouched
      objClone = objRN.cloneNode(true);
      objClone.removeAttribute("jsxselected");

      if(objExist) {
        //replace the existing node with a clone of what was asked to be persisted
        objExist.getParent().replaceNode(objClone,objExist);
      } else {
        //append the clone; this record is not yet part of the persistent store
        if(!objPRN) objPRN = Cache.getDocument(TYPE).getRootNode();
        objPRN.appendChild(objClone);
      }
      var objRN = objClone;
    }

    //cache if not cached (only cache no more frequently than once every 30 seconds)
    window.clearTimeout(Cache.serialize_throttle);
    Cache.serialize_throttle = window.setTimeout(function() { Cache.serialize(TYPE); },Cache.TIMEOUT);

    return objRN;
  };


  /**
   * Deletes the CDF record from one of the cacheable CDF documents used by the app (defined by TYPE)
   * @param TYPE {String} one of: searchHistory (hard cache), _searchHistory (soft cache)
   * @param strId {String} CDF jsxid
   */
  Cache.deleteRecord = function(TYPE,strId) {
    //check the cache for the posting
    var objRN = Cache.getRecord(TYPE,strId);
    if(objRN) {
      objRN.getParent().removeChild(objRN);
      //cache if not cached (only cache no more frequently than once every 30 seconds)
      window.clearTimeout(Cache.serialize_throttle);
      Cache.serialize_throttle = window.setTimeout(function() { Cache.serialize(TYPE); },Cache.TIMEOUT);
      return objRN;
    }
  };


  /**
   * Persists the given xml document to the permanant data store; for now only the hard cache (searchHistory) is persisted
   * @param TYPE {String} one of: searchHistory (hard cache)
   */
  Cache.serialize = function(TYPE) {
    if(Cache.isEnabled())
      dojo.storage.put(TYPE,Cache.getDocument(TYPE).serialize(true));
  };


  /**
   * Returns a persisted document from the local persistent store (dojo.storage)
   * @param TYPE {String} one of: searchHistory (hard cache)
   */
  Cache.deserialize = function(TYPE) {
    //jsx3.log("to do: restore from dojo storage");
    if(typeof(window.dojo) != "undefined" && dojo.storage) {
      var strXML = dojo.storage.get(TYPE);
      if(!jsx3.util.strEmpty(strXML)) {
        var objXML = jsx3.xml.CDF.Document.newDocument();
        objXML.loadXML(strXML);
        if(objXML.hasError()) {
          jsx3.log("Error restoring the stored document, " + TYPE + ". Description: " + objXML.getError().description);
        } else {
          jsx3.log("Restoring the document, '" + TYPE + "', from dojo storage (string) to GI (CDF).");
          gicx.APP.getCache().setDocument(TYPE,objXML);
          return objXML;
        }
      }
    }
  };

});



